package com.ctshk.rpc.localfun.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.CurrencyRateExchangeConstant;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.rpc.localfun.dto.*;
import com.ctshk.rpc.localfun.entity.LocalFunProduct;
import com.ctshk.rpc.localfun.entity.LocalFunProductCostStrategy;
import com.ctshk.rpc.localfun.entity.LocalFunProductCostStrategySpecStock;
import com.ctshk.rpc.localfun.enums.ProductCenterEnum;
import com.ctshk.rpc.localfun.mapper.*;
import com.ctshk.rpc.localfun.req.LocalFunProductCostReq;
import com.ctshk.rpc.localfun.service.ILocalFunCostPriceService;
import com.ctshk.rpc.localfun.util.NumberUtil;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import com.google.common.collect.Lists;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description
 * @author wansi <gaylen15527491065@yeah.net>
 * @date 2021/3/26
 */
@DubboService
public class LocalFunCostPriceServiceImpl extends ServiceImpl<LocalFunProductCostStrategySpecStockMapper, LocalFunProductCostStrategySpecStock> implements ILocalFunCostPriceService {
    @Autowired
    private LocalFunProductCostStrategyVaildDateMapper costStrategyVaildDateMapper;
    @Autowired
    private LocalFunProductCostStrategyMapper costStrategyMapper;

    //汇率服务
    @DubboReference
    private IMainDataCurrencyService mainDataCurrencyService;

    @Autowired
    private LocalFunProductMapper localFunProductMapper;

    @DubboReference
    private ILocalFunCostPriceService iLocalFunCostPriceService;

    @DubboReference
    private ISysDepartmentService iSysDepartmentService;

    @Autowired
    private LocalFunProductSaleRecordMapper saleRecordMapper;

    /**
     * 港币币种名称
     */
    private static final String HKD_NAME = "HKD";

    @Override
    public List<LocalFunProductCostDTO> getProductCostList(LocalFunProductCostReq localFunProductCostReq) {
        List<LocalFunProductCostDTO> destinationList = Lists.newArrayListWithExpectedSize(10);
        //获取查询时间对应的幅加策略相关信息
        LocalFunOfflineSelCustomDTO increaseFee = getIncreaseFee(localFunProductCostReq);
        if(increaseFee == null){
            return Lists.newArrayListWithExpectedSize(1);
        }
        //获取产品成本价结果集
        List<CostStrategyStockDTO> productCostList = baseMapper.getProductCostList(localFunProductCostReq);
        if(CollectionUtils.isEmpty(productCostList)){
            return Lists.newArrayListWithExpectedSize(1);
        }

        //获取查询时间对应的成本库存信息
        List<CostStrategyStockDTO> singletonStocks = productCostList.stream().filter(entity -> localFunProductCostReq.getQueryDate().compareTo(entity.getTimeBegin()) >= 0 &&
                localFunProductCostReq.getQueryDate().compareTo(entity.getTimeEnd()) <= 0).collect(Collectors.toList());

        if(CollectionUtils.isEmpty(singletonStocks)) {
            return Lists.newArrayListWithExpectedSize(1);
        }


        //将币种转港币兑换率
        CostStrategyStockDTO costStrategyStockDTO = singletonStocks.stream().findFirst().orElse(null);
        BigDecimal exchangeRate = costStrategyStockDTO.getExchangeRate() != null ? new BigDecimal(costStrategyStockDTO.getExchangeRate()) : BigDecimal.ZERO;

        //遍历产品成本策略各个规格下的成本价
        for(CostStrategyStockDTO costStrategyStock : singletonStocks){
            //获取到使用时间对应的成本策略：成本价
            BigDecimal costPrice = costStrategyStock.getCostPrice();
            costPrice = costPrice == null ? BigDecimal.ZERO : costPrice.multiply(exchangeRate);

            if(increaseFee != null){
                if(ProductCenterEnum.AMOUNT.getChannelCode().equals(increaseFee.getAdjustType())){
                    //成本价+加辐费
                    costPrice = costPrice.add(Objects.isNull(increaseFee.getAmount()) ? BigDecimal.ZERO : increaseFee.getAmount());
                }else {
                    costPrice = costPrice.add(costPrice.multiply(Objects.isNull(increaseFee.getPercent())?BigDecimal.ZERO:new BigDecimal(increaseFee.getPercent()*0.01)));
                }
            }

            destinationList.add(LocalFunProductCostDTO.builder()
                    .price(costPrice.add(getReserveCharge(costStrategyStock)))
                    /*成本策略规格ID*/
                    .attr1Id(costStrategyStock.getAttr1Id())
                    /*成本策略规格Name*/
                    .attr1Name(costStrategyStock.getAttr1Name())
                    /*成本策略规格ID*/
                    .attr2Id(costStrategyStock.getAttr2Id())
                    /*成本策略规格Name*/
                    .attr2Name(costStrategyStock.getAttr2Name())
                    /*币种ID*/
                    .currencyId(null)
                    /*币种名称*/
                    .currencyName(HKD_NAME)
                    .timeBegin(costStrategyStock.getTimeBegin())
                    .timeEnd(costStrategyStock.getTimeEnd())
                    /*产品ID*/
                    .productId(localFunProductCostReq.getProductId())
                    /*幅加策略ID*/
                    .increaseStrategyId(increaseFee == null ? null :increaseFee.getIncreaseStrategyId())
                    /*产品成本ID*/
                    .costId(costStrategyStock.getCostId())

                    //餘票 加幅策略配置每日可售數，則拿每日餘票=每日可售數-每日已售數 ；否則加幅策略為無限制，則拿產品庫存餘票
                    .totalStock(getTotalStock(increaseFee,costStrategyStock,localFunProductCostReq))
                    .build());

        }

        //查找具体规格的产品加幅費用
        if(CollectionUtils.isNotEmpty(destinationList) && localFunProductCostReq.getAttrId1() != null
                && localFunProductCostReq.getAttrId2() != null){
            return destinationList.stream().filter(en->localFunProductCostReq.getAttrId1().equals(en.getAttr1Id()) &&
                    localFunProductCostReq.getAttrId2().equals(en.getAttr2Id())).collect(Collectors.toList());
        }
        return destinationList;
    }

    private String getTotalStock(LocalFunOfflineSelCustomDTO increaseFee, CostStrategyStockDTO costStrategyStock, LocalFunProductCostReq localFunProductCostReq) {
        if(increaseFee != null){
            //1：限购售额
            if(increaseFee.getIsLimit() != null && increaseFee.getIsLimit() == 1){
                //今日可售額
                Integer limitNum = increaseFee.getLimitNum();
                //產品总庫存
                Integer solidStock = costStrategyStock.getTotalStock() == null ? 0 : costStrategyStock.getTotalStock();

                if(limitNum == null){
                    //餘票=庫存-產品已售額
                    int surplusNumber = saleRecordMapper.selectSoldStockCount(localFunProductCostReq.getProductId());
                    return solidStock-surplusNumber +"";
                }else {
                    //今日可售額 大於庫存，余票=总庫存-產品已售額
                    if(limitNum > solidStock){
                        int surplusNumber = saleRecordMapper.selectSoldStockCount(localFunProductCostReq.getProductId());
                        return solidStock-surplusNumber +"";
                    }else {
                        if(limitNum == 0){
                            return "0";
                        }

                        int line; // 1.线上 2.线下
                        int channel; //1:自营 2:代理商 3:官方渠道 4:第三方
                        Long relationId;//线下自定义为customId = 1L 所有部门 ； customeId=2L 所有代理商 ； 其他则是关联ID,线上为各自的渠道ID

                        //线下渠道类型（1：自营渠道 2：代理商） ; null--官方平台、第三方平台（暂不考虑）
                        if(increaseFee.getChannelType() == null){
                            //官方平台渠道
                            line = 1;
                            channel =3;
                            relationId = increaseFee.getRelationId();
                        }else {
                            //自营渠道 已售数 1：自营渠道 2：代理商
                            //自营渠道 已售数
                            if(increaseFee.getChannelType() == 1){
                                line = 2;
                                channel =1;
                                //选择所有部门 customId = 1L 所有部门;否则赋值关联ID
                                if(increaseFee.getVisableType() == 2){
                                    relationId = 1L;
                                }else {
                                    relationId = increaseFee.getRelationId();
                                }
                            }
                            //代理商渠道已售数
                            else {
                                line = 2;
                                channel =2;

                                //选择所有代理商 customId = 2L 所有部门;否则赋值关联ID
                                if(increaseFee.getVisableType() == 2){
                                    relationId = 2L;
                                }else {
                                    relationId = increaseFee.getRelationId();
                                }
                            }
                        }
                        //餘票=今日可售額-渠道对应的今日已售額
                        int soldStockCount = saleRecordMapper.selectOnlineTodaySoldStockCount(localFunProductCostReq.getProductId(),Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()),relationId,line,channel);
                        return limitNum -soldStockCount +"";
                    }
                }
            }
            //2.不限售額，余票=总庫存-產品已售額
            else {
                Integer solidStock = costStrategyStock.getTotalStock();
                //餘票=庫存-產品已售額
                int surplusNumber = saleRecordMapper.selectSoldStockCount(localFunProductCostReq.getProductId());
                return solidStock-surplusNumber +"";
            }




        }else {
            return costStrategyStock.getSurplusStock() +"";
        }
    }


    private BigDecimal getReserveCharge(CostStrategyStockDTO costStrategyStock) {
        if(costStrategyStock.getReserveCharge() == null){
            return BigDecimal.ZERO;
        }
        if(costStrategyStock.getReserveChargeType() == 1){
            return costStrategyStock.getReserveCharge() == null ? BigDecimal.ZERO : costStrategyStock.getReserveCharge();
        }else {
            BigDecimal reserveCharge = costStrategyStock.getReserveCharge();
            if(reserveCharge == null){
                reserveCharge = BigDecimal.ZERO;
            }
            return costStrategyStock.getCostPrice().multiply(reserveCharge.multiply(new BigDecimal(0.01)));
        }
    }

    @Override
    public LocalFunProductTicketDTO getLocalFunProductTicketDTO(String productTicketsId, Long productId, Long userId, LocalDateTime gmtCreate) {
        LocalFunProductTicketDTO dto = new LocalFunProductTicketDTO();
        LocalFunProduct localFunProduct = localFunProductMapper.selectById(productId);

        String[] split = StringUtils.delimitedListToStringArray(productTicketsId,",");
        List<Long> ids = Arrays.stream(split).filter(id->StringUtils.isNotEmpty(id) && !"null".equals(id)).map(id -> Long.valueOf(id)).collect(Collectors.toList());
        QueryWrapper<LocalFunProductCostStrategySpecStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(LocalFunProductCostStrategySpecStock::getProductId,productId);
        if(ids.get(0) != null){
            queryWrapper.lambda().eq(LocalFunProductCostStrategySpecStock::getAttr1Id,ids.get(0));
        }
        if(ids.size() > 1 && ids.get(1) != null){
            queryWrapper.lambda().eq(LocalFunProductCostStrategySpecStock::getAttr2Id,ids.get(1));
        }
        List<LocalFunProductCostStrategySpecStock> costStrategySpecStocks = baseMapper.selectList(queryWrapper);

        LocalFunProductCostReq req = new LocalFunProductCostReq();
        req.setUserId(userId);
        req.setProductId(productId);
        if(gmtCreate.toLocalDate() == null){
            req.setQueryDate(gmtCreate.toLocalDate());
        }else {
            req.setQueryDate(LocalDate.now());
        }
        req.setChannelType(1);
        LocalFunOfflineSelCustomDTO increaseFee = iLocalFunCostPriceService.getIncreaseFee(req);

        if(CollectionUtils.isEmpty(costStrategySpecStocks)) {
            return dto;
        }
        LocalFunProductCostStrategySpecStock costStrategySpecStock = costStrategySpecStocks.stream().findFirst().orElse(null);
        if(costStrategySpecStock!=null){
            BigDecimal costPrice = costStrategySpecStock.getCostPrice();

            LocalFunProductCostStrategy localFunProductCostStrategy = costStrategyMapper.selectById(costStrategySpecStock.getCostId());

            BigDecimal exchangeRate = localFunProductCostStrategy.getExchangeRate() != null ? new BigDecimal(localFunProductCostStrategy.getExchangeRate()):BigDecimal.ZERO;

            //汇率转换成港币
            costPrice = costPrice.multiply(exchangeRate);

            //1 金额 预订服务费
            if(1 == localFunProduct.getReserveChargeType()){
                dto.setCharge(localFunProduct.getReserveCharge());
            }
            // 2 百分比
            if(2 == localFunProduct.getReserveChargeType()){
                BigDecimal fee = costPrice.multiply(localFunProduct.getReserveCharge().multiply(new BigDecimal(0.01)));
                dto.setCharge(fee);
            }

            //加辐费
            if(increaseFee != null){
                if(increaseFee.getAdjustType() == 1){
                    costPrice = costPrice.add(increaseFee.getAmount());
                }else {
                    costPrice = costPrice.add(costPrice.multiply(new BigDecimal(increaseFee.getPercent()).multiply(new BigDecimal(0.01))));
                }
            }
            dto.setCostPrice(costPrice);
        }

        return dto;
    }

    /**
     * 获取查询时间对应的幅加策略相关信息
     * @param localFunProductCostReq
     * @return
     */
    @Override
    public LocalFunOfflineSelCustomDTO getIncreaseFee(LocalFunProductCostReq localFunProductCostReq){

        switch (localFunProductCostReq.getChannelType()){
            //自營渠道
            case 1:
                return selCustomFee(localFunProductCostReq);
            //代理商
            case 2:
                return agentFee(localFunProductCostReq);
            default:
                return  null;
        }
    }

    /**
     * 代理商加幅
     * @param localFunProductCostReq
     * @return
     */
    private LocalFunOfflineSelCustomDTO agentFee(LocalFunProductCostReq localFunProductCostReq) {
        //按照查询时间找到唯一对应的幅加策略 暂时只处理线下自营渠道
        List<LocalFunOfflineSelCustomDTO> productSaleList = baseMapper.getProductAgentSaleList(localFunProductCostReq);
        if(CollectionUtils.isNotEmpty(productSaleList)){

            Map<Integer, List<LocalFunOfflineSelCustomDTO>> visableMap = productSaleList.stream().collect(Collectors.groupingBy(LocalFunOfflineSelCustomDTO::getVisableType));

            //唯一对应的幅加策略下，线下自营->选择的权限也是单项，取第一个数据获取权限选择项：visableType
            LocalFunOfflineSelCustomDTO saleEntity = productSaleList.stream().findFirst()
                    .orElse(LocalFunOfflineSelCustomDTO.builder().visableType(-99).build());

            switch (saleEntity.getVisableType()){
                case ProductCenterEnum.SEL_CUSTOM_FORBID:
                    //禁销
                    List<LocalFunOfflineSelCustomDTO> selCustomDTOS = visableMap.get(ProductCenterEnum.SEL_CUSTOM_FORBID);
                    if(CollectionUtils.isEmpty(selCustomDTOS)){
                        return null;
                    }
                    break;
                case ProductCenterEnum.ALL_DEPT_SALE:
                    //所有部门
                    List<LocalFunOfflineSelCustomDTO> deptCustomDTOS = visableMap.get(ProductCenterEnum.ALL_DEPT_SALE);
                    if(CollectionUtils.isNotEmpty(deptCustomDTOS)){
                        return deptCustomDTOS.stream().findFirst().orElse(null);
                    }
                case ProductCenterEnum.PERSONAL_SALE:
                    //指定部门/人
                    List<LocalFunOfflineSelCustomDTO> personalCustomDTOS = visableMap.get(ProductCenterEnum.PERSONAL_SALE);
                    if(CollectionUtils.isNotEmpty(personalCustomDTOS)){

                        if(localFunProductCostReq.getAgentId() == null || localFunProductCostReq.getAgentId() == 0L){
                            return null;
                        }
                        List<LocalFunOfflineSelCustomDTO> personals = personalCustomDTOS.stream()
                                .filter(entity -> entity.getRelationId().equals(localFunProductCostReq.getAgentId())).collect(Collectors.toList());

                        return personals.stream().findFirst().orElse(null);
                    }
                default:
                    break;

            }
        }
        return null;
    }

    /**
     * 線下自營渠道-加幅
     * @param localFunProductCostReq
     * @return
     */
    private LocalFunOfflineSelCustomDTO selCustomFee(LocalFunProductCostReq localFunProductCostReq) {
        //按照查询时间找到唯一对应的幅加策略 暂时只处理线下自营渠道
        List<LocalFunOfflineSelCustomDTO> productSaleList = baseMapper.getProductSaleList(localFunProductCostReq);
        if(CollectionUtils.isNotEmpty(productSaleList)){

            Map<Integer, List<LocalFunOfflineSelCustomDTO>> visableMap = productSaleList.stream().collect(Collectors.groupingBy(LocalFunOfflineSelCustomDTO::getVisableType));

            //唯一对应的幅加策略下，线下自营->选择的权限也是单项，取第一个数据获取权限选择项：visableType
            LocalFunOfflineSelCustomDTO saleEntity = productSaleList.stream().findFirst()
                    .orElse(LocalFunOfflineSelCustomDTO.builder().visableType(-99).build());

            switch (saleEntity.getVisableType()){
                case ProductCenterEnum.SEL_CUSTOM_FORBID:
                    //禁销
                    List<LocalFunOfflineSelCustomDTO> selCustomDTOS = visableMap.get(ProductCenterEnum.SEL_CUSTOM_FORBID);
                    if(CollectionUtils.isEmpty(selCustomDTOS)){
                        return null;
                    }
                    break;
                case ProductCenterEnum.ALL_DEPT_SALE:
                    //所有部门
                    List<LocalFunOfflineSelCustomDTO> deptCustomDTOS = visableMap.get(ProductCenterEnum.ALL_DEPT_SALE);
                    if(CollectionUtils.isNotEmpty(deptCustomDTOS)){
                        return deptCustomDTOS.stream().findFirst().orElse(null);
                    }
                case ProductCenterEnum.PERSONAL_SALE:
                    //指定部门/人
                    List<LocalFunOfflineSelCustomDTO> personalCustomDTOS = visableMap.get(ProductCenterEnum.PERSONAL_SALE);
                    if(CollectionUtils.isNotEmpty(personalCustomDTOS)){
                        List<String> userIdsByUserId = getUserIdsByUserId(localFunProductCostReq.getUserId());
//                        SysDepartmentDTO sysDepartmentDTO = iSysDepartmentService.queryByUserId(localFunProductCostReq.getUserId());
//
                        List<LocalFunOfflineSelCustomDTO> personals = personalCustomDTOS.stream()
                                .filter(entity -> entity.getCheckType() != null
                                        && ProductCenterEnum.PERSONAL_CHOOSE == entity.getCheckType().intValue()
                                        && entity.getRelationId() != null && userIdsByUserId.contains(String.valueOf(entity.getRelationId()))).collect(Collectors.toList());
//
//                        //策略加幅既包含部门又包含人，以人的权限为主
                        if(personals.size() >= 2){
                            return personals.stream().filter(entity->ProductCenterEnum.PERSONAL_CHOOSE == entity.getCheckType())
                                    .findFirst().orElse(null);
                        }

                        return personals.stream().findFirst().orElse(null);
                    }
                default:
                    break;

            }
        }
        return null;
    }

    /**
     * 根据当前用户去查找对应的用户权限
     *
     * @param id
     * @return
     */
    private List<String> getUserIdsByUserId(Long id) {
        List<Long> longs = iSysDepartmentService.queryIdsByUserId(id);
        longs.add(id);
        String stringBuffer = "";
        for (Long aLong : longs) {
            stringBuffer += aLong.toString() + ",";
        }
        if (!"".equals(stringBuffer)) {
            stringBuffer = stringBuffer.substring(0, stringBuffer.length() - 1);
        }
        return Lists.newArrayList(stringBuffer.split(","));
    }
}
